home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Windows News 2005 February
/
WN_129_CD.iso
/
Windows
/
Extensions Firefox
/
Bookmarks Synchronizer
/
bookmarksftp1_0_1.xpi
/
chrome
/
bookmarksftp.jar
/
content
/
bmsyncRDFService.js
< prev
next >
Wrap
Text File
|
2004-10-17
|
26KB
|
846 lines
function BookmarksSynchronizerXBEL(){
this._init();
}
BookmarksSynchronizerXBEL.prototype=
{
settings:null,
_tempDoc:null,
_rdfService : null,
_ds : null,
_tempc : null,
_rdfcu:null,
get _pid(){
return "+//IDN python.org//DTD XML Bookmark Exchange Language 1.0//EN//XML";
},
get _sid(){
return "http://pyxml.sourceforge.net/topics/dtds/xbel-1.0.dtd";
},
get _owner(){
return "Mozilla";
},
_init:function()
{
this.settings=new BookmarksSynchronizerSettings();
this._rdfService = Components.classes["@mozilla.org/rdf/rdf-service;1"]
.getService(Components.interfaces.nsIRDFService);
this._ds=this._rdfService.GetDataSource( "rdf:bookmarks" );
this._ds.QueryInterface(Components.interfaces.nsIBookmarksService);
this._tempc = Components.classes["@mozilla.org/rdf/container;1"]
.getService(Components.interfaces.nsIRDFContainer);
this._rdfcu = Components.classes['@mozilla.org/rdf/container-utils;1']
.getService(Components.interfaces.nsIRDFContainerUtils);
this._urlArc=this._rdfService.GetResource( "http://home.netscape.com/NC-rdf#URL");
this._nameArc=this._rdfService.GetResource( "http://home.netscape.com/NC-rdf#Name");
this._descArc=this._rdfService.GetResource("http://home.netscape.com/NC-rdf#Description");
this._typeArc=this._rdfService.GetResource("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
this._keywordArc= this._rdfService.GetResource("http://home.netscape.com/NC-rdf#ShortcutURL");
this._iconArc= this._rdfService.GetResource("http://home.netscape.com/NC-rdf#Icon");
this._typeArc=this._rdfService.GetResource("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
this._feedArc= this._rdfService.GetResource("http://home.netscape.com/NC-rdf#FeedURL");
this._sideArc= this._rdfService.GetResource("http://home.netscape.com/NC-rdf#WebPanel");
this._dateArc= this._rdfService.GetResource("http://home.netscape.com/NC-rdf#BookmarkAddDate");
this._bookmarkVal=this._rdfService.GetResource("http://home.netscape.com/NC-rdf#Bookmark");
this._folderVal=this._rdfService.GetResource("http://home.netscape.com/NC-rdf#Folder");
this._livemarkVal=this._rdfService.GetResource("http://home.netscape.com/NC-rdf#Livemark");
},
/* Bookmarks -> XBEL */
_initXBELElement:function(resource)
{
var title= this._getLiteral(resource,this._nameArc);
var desc= this._getLiteral(resource,this._descArc);
if(title)
this._addTitle(this._tempDoc.documentElement,title);
if(desc)
this._addDesc(this._tempDoc.documentElement,desc);
if(! this._isBookmarkedResource(this._rdfToolbar,resource))
return;
this._addInfo(this._tempDoc.documentElement,[["BookmarksToolbarFolder",this._rdfToolbar.Value]]);
},
get _rdfToolbar()
{
return this._ds.getBookmarksToolbarFolder();
},
get _root(){
return this._rdfService.GetResource(this.settings.selectedFolder);
},
_isBookmarkedResource:function(aResource,aRoot)
{
if(!aResource || !aRoot) return false;
try{
aResource.QueryInterface(Components.interfaces.nsIRDFResource);
aRoot.QueryInterface(Components.interfaces.nsIRDFResource);
}catch(e){return false;}
var folders=[aRoot];
var uri=aResource.Value;
while(folders.length>0)
{
var folder=folders.shift();
this._tempc.Init(this._ds, folder);
var elements=this._tempc.GetElements();
while(elements.hasMoreElements())
{
var element=elements.getNext();
element.QueryInterface(Components.interfaces.nsIRDFResource);
if(element.EqualsString ( uri ))
return true;
else if(this._rdfcu.IsContainer(this._ds,element))
folders.push(element);
}
}
return false;
},
get source()
{
var doctype=document.implementation
.createDocumentType("xbel",this._pid,this._sid);
this._tempDoc=document.implementation
.createDocument("","xbel",doctype);
var serializer= new XMLSerializer();
var enableLM=this.settings.getBool("livemark",true);
var enableKW=this.settings.getBool("keyword",true);
var enableFI=this.settings.getBool("favicon",true);
var enableWP=this.settings.getBool("webpanel",true);
try{
if(!this._ds.isBookmarkedResource(this._root)||this._resolveType(this._root)!="Folder")
return "";
}catch(e){return "";}
this._initXBELElement(this._root);
var foldersets=[[this._tempDoc.documentElement,this._root]];
while(foldersets.length>0)
{
var folderset= foldersets.shift();
var folder=folderset[1].QueryInterface(Components.interfaces.nsIRDFResource);
this._tempc.Init(this._ds, folder);
var elements=this._tempc.GetElements();
while(elements.hasMoreElements())
{
var resource=elements.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
var uri=resource.Value.replace(/\:/g,"%3A");
var name=this._getLiteral(resource,this._nameArc);
var desc=this._getLiteral(resource,this._descArc);
var url="";
var info=[];
switch (this._resolveType(resource)) {
case "BookmarkSeparator":
this._addSeparator(folderset[0]);
break;
case "IEFavorite":
case "ImmutableBookmark":
case "Bookmark":
url=this._getLiteral(resource,this._urlArc);
if(enableKW){
var keyword=this._getLiteral(resource,this._keywordArc);
if(keyword)
info.push(["ShortcutURL",keyword]);
}
if(enableFI){
var icon=this._getLiteral(resource,this._iconArc);
if(icon)
info.push(["Icon",icon]);
}
if(enableWP){
var sidebar=this._getLiteral(resource,this._sideArc);
if(sidebar)
info.push(["WebPanel",sidebar]);
}
this._addBookmark(folderset[0],uri,name,desc,url,info);
break;
case "Livemark":
url=this._getLiteral(resource,this._urlArc);
info=(enableLM)? [["FeedURL",this._getLiteral(resource,this._feedArc)]]:[];
this._addBookmark(folderset[0],uri,name,desc,url,info);
break;
case "Folder":
case "PersonalToolbarFolder":
case "IEFavoriteFolder":
var newFolder=this._addFolder(folderset[0],uri,name,desc);
foldersets.push([newFolder,resource]);
break;
break;
case "LivemarkBookmark":
break;
default:
}
}
}
return "<?xml version=\"1.0\" encoding=\""+this.settings.charset+"\"?>\n"
+ this.convertFromUnicode(this.settings.charset,
this.settings.tags + serializer.serializeToString(this._tempDoc));
},
_resolveType: function (aResource)
{
var type = this._ds.GetTarget(aResource, this._typeArc, true);
if(type){
var uri=type.QueryInterface(Components.interfaces.nsIRDFResource).Value;
return uri.split("#")[1];
} else if(this._rdfcu.IsContainer(this._ds,aResource))
return "Folder";
else if (this._getLiteral(aResource, this._urlArc))
return "Bookmark";
return "";
},
_getLiteral:function(resource,arc)
{
var target=this._ds.GetTarget(resource, arc, true);
if(target) return target.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
else return "";
},
_addTitle:function(element,str)
{
var title=this._tempDoc.createElement("title");
var textnode=this._tempDoc.createTextNode(str);
title.appendChild(textnode);
element.appendChild(title);
},
_addInfo:function(aElement , aData)
{
if(aData.length==0)
return;
var info=this._tempDoc.createElement("info");
var metadata=this._tempDoc.createElement("metadata");
metadata.setAttribute("owner", this._owner);
while(aData.length >0)
{
var temp=aData.shift();
metadata.setAttribute(temp[0], temp[1]);
}
info.appendChild(metadata);
aElement.appendChild(info);
},
_addDesc:function(element,str)
{
var title=this._tempDoc.createElement("desc");
var textnode=this._tempDoc.createTextNode(str);
title.appendChild(textnode);
element.appendChild(title);
},
_addBookmark:function(element,uri,title,desc,url,info)
{
var bookmark=this._tempDoc.createElement("bookmark");
bookmark.setAttribute("id",uri);
bookmark.setAttribute("href",url);
this._addTitle(bookmark,title);
if(info.length>0)
this._addInfo(bookmark,info);
if(desc)
this._addDesc(bookmark,desc);
element.appendChild(bookmark);
},
_addFolder:function(element,uri,title,desc)
{
var folder=this._tempDoc.createElement("folder");
folder.setAttribute("id",uri);
this._addTitle(folder,title);
if(desc)
this._addDesc(folder,desc);
element.appendChild(folder);
return folder;
},
_addSeparator:function(element)
{
var sep=this._tempDoc.createElement("separator");
element.appendChild(sep);
},
convertFromUnicode:function(aCharset, aSrc )
{
try{
var unicodeConverter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
.createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
unicodeConverter.charset = aCharset;
return unicodeConverter.ConvertFromUnicode( aSrc );
}catch(e){alert(e);}
return aSrc;
},
/* XBEL -> Bookmarks */
_icons:[],
_xbelToolbar:null,
set source(aStr)
{
this._icons=[];
this._xbelToolbar=null;
/* preprocess */
if(!this._setDocument(aStr))
throw "bmsync:noxbel";
if(!this._rdfcu.IsContainer(this._ds,this._root))
throw "bmsync:foldernotfound";
this._xbelToolbar=this.__xbelToolbar;
if( !this._xbelToolbar &&
this._isBookmarkedResource(this._rdfToolbar,this._root) &&
!confirm(this.settings.getString("losetoolbarfolder")))
throw "bmsync:usercancel";
var failure=false;
/* main process */
this._ds.beginUpdateBatch();
this._killBrowser();
try
{
if(this.settings.getBool("merge",false))
this._merge();
else
{
this._cleanup();
this._subprocess();
}
}catch(e){alert(e); failure=true;}
try{
this._updateIcons();
}catch(e){}
this._reliveBrowser();
this._ds.endUpdateBatch();
this._ds.transactionManager.clear();
if(failure)
throw "bmsync:unexpected";
},
_setDocument:function(aStr)
{
if(!aStr)
return false;
var parser=new DOMParser();
this._tempDoc= parser.parseFromString(this.convertToUnicode(aStr),"text/xml");
if(!this._isXBEL())
return false;
return true;
},
_getBookmarkByName:function(aName)
{
if(!aName)
return null;
var elements=this._tempc.GetElements();
while(elements.hasMoreElements())
{
var element=elements.getNext()
.QueryInterface(Components.interfaces.nsIRDFResource);
var type=this._resolveType(element);
if(type == "Bookmark" || type == "Livemark")
{
var target=this._ds.GetTarget(element,this._nameArc,true);
if(target && target.QueryInterface(Components.interfaces.nsIRDFLiteral).Value == aName)
return element;
}
}
return null;
},
_getFolderByName:function(aName)
{
var elements=this._tempc.GetElements();
while(elements.hasMoreElements())
{
var element=elements.getNext()
.QueryInterface(Components.interfaces.nsIRDFResource);
if(this._resolveType(element) == "Folder")
{
var target=this._ds.GetTarget(element,this._nameArc,true);
if(target &&
target.QueryInterface(Components.interfaces.nsIRDFLiteral).Value == aName)
return element;
}
}
return null;
},
get _date()
{
var date= ((new Date()).getTime())*1000;
date=parseInt(date).toString();
return date;
},
_changeBookmark: function (bookmark,data)
{
const trueVal=this._rdfService.GetLiteral("true");
/*0=id,1=name,2=url,3=keyword,4=desc,5=feedURL,6=webPanel*/
var date=this._rdfService.GetDateLiteral(this._date);
this._assert(bookmark,this._dateArc,date);
if(data[1])
this._assert(bookmark,this._nameArc,this._rdfService.GetLiteral(data[1]));
if(data[2])
this._assert(bookmark,this._urlArc,this._rdfService.GetLiteral(data[2]));
if(data[3])
this._assert(bookmark,this._keywordArc,this._rdfService.GetLiteral(data[3]));
if(data[4])
this._assert(bookmark,this._descArc,this._rdfService.GetLiteral(data[4]));
if(date[6])
this._assert(bookmark,this._sideArc,trueVal);
},
_merge:function()
{
var foldersets=[[this._tempDoc.documentElement,this._root]];
var folderset=null;
const trueVal=this._rdfService.GetLiteral("true");
while(foldersets.length > 0)
{
folderset=foldersets.shift();
var childNodes=folderset[0].childNodes;
var resource= folderset[1];
var title="";
var desc="";
var id="";
this._tempc.Init(this._ds, resource);
for(var i =0; i< childNodes.length; i++)
{
var element=childNodes[i];
if(element.nodeType==1)
{
id=this._getProp(element,"id");
var oldResource=null;
if(id)
oldResource=this._rdfService.GetResource(id);
var oldDataExists= ( oldResource && this._tempc.IndexOf(oldResource) > -1)
switch(element.nodeName.toUpperCase())
{
case "BOOKMARK":
var bookmark;
var data=this._getBookmarkData(element);
if( oldDataExists )
var bookmark=oldResource;
else
{
bookmark=this._getBookmarkByName(data[1]);
}
if(!bookmark)
bookmark=this._createBookmark(id,data[5]);
this._changeBookmark(bookmark,data);
break;
case "FOLDER":
title=this._getTitle(element);
desc=this._getDesc(element);
var folder=null;
if( oldDataExists )
folder=oldResource;
else
{
folder=this._getFolderByName(title);
if(!folder)
folder=this._ds.createFolderInContainer(title,resource,0);
}
if(desc)
this._assert( folder,this._descArc,
this._rdfService.GetLiteral(desc));
foldersets.push([element, folder]);
if(this._xbelToolbar && id==this._xbelToolbar)
this._ds.setBookmarksToolbarFolder(folder);
break;
case "SEPARATOR":
break;
}
}
}
}
},
_cleanup:function()
{
var folders=[this._root];
while(folders.length>0)
{
var folder= folders.shift();
folder.QueryInterface(Components.interfaces.nsIRDFResource);
this._tempc.Init(this._ds, folder);
var elements=this._tempc.GetElements();
while(elements.hasMoreElements())
{
var resource=elements.getNext();
this._tempc.RemoveElement(resource,false);
if(this._rdfcu.IsContainer(this._ds,resource))
folders.push(resource);
else this._unassert(resource);
}
if(folder.Value!=this._root.Value)
this._unassert(folder);
}
},
_updateIcons:function()
{
const stringStream=Components.classes["@mozilla.org/io/string-input-stream;1"]
.createInstance(Components.interfaces.nsIStringInputStream);
const binStream = Components.classes['@mozilla.org/binaryinputstream;1']
.createInstance(Components.interfaces.nsIBinaryInputStream);
while(this._icons.length>0)
{
var icon=this._icons.shift();
if(!icon[1].match(/^data\:([a-z\-\/]+)\;base64\,/))
continue;
var type=RegExp.$1;
var stream=this.settings._ioService.newChannel(icon[1],null,null).open();
binStream.setInputStream(stream);
var array=binStream.readByteArray(stream.available());
this._ds.updateBookmarkIcon(icon[0],type,array,array.length);
}
return null;
},
undo:function()
{
if(!this.settings.undoable)
return;
var merge=this.settings.getBool("merge",false);
var toolbar=this._rdfService.GetResource(this.settings.cacheToolbar);
this.settings.setBool("merge",false);
try{
this.settings.redoCache=this.source;
this.source=this.settings.undoCache;
this.settings.undoCache="";
if(this._ds.isBookmarkedResource(toolbar))
this._ds.setBookmarksToolbarFolder(toolbar);
}catch(e){alert(e);}
this.settings.setBool("merge",merge);
},
redo:function()
{
if(!this.settings.redoable)
return;
var merge=this.settings.getBool("merge",false);
this.settings.setBool("merge",false);
try{
this.settings.undoCache=this.source;
this.source=this.settings.redoCache;
this.settings.redoCache="";
}catch(e){alert(e);}
this.settings.setBool("merge",merge);
},
updateUndoCache:function()
{
if(!this.settings.getBool("session.enabled"))
return;
this.settings.cacheFolder=this.settings.selectedFolder;
this.settings.cacheToolbar=this._rdfToolbar.Value;
var merge=this.settings.getBool("merge",false);
this.settings.setBool("merge",false);
try{
this.settings.undoCache=this.source;
this.settings.redoCache="";
}catch(e){alert(e);}
this.settings.setBool("merge",merge);
},
_subprocess:function()
{
var foldersets=[[this._tempDoc.documentElement,this._root]];
var folderset=null;
const trueVal=this._rdfService.GetLiteral("true");
while(foldersets.length > 0)
{
folderset=foldersets.shift();
var childNodes=folderset[0].childNodes;
var resource= folderset[1];
var title="";
var desc="";
var id="";
for(var i =0; i< childNodes.length; i++)
{
var element=childNodes[i];
if(element.nodeType==1)
{
id=this._getProp(element,"id");
switch(element.nodeName.toUpperCase())
{
case "BOOKMARK":
var data=this._getBookmarkData(element);
if(!data[5]){
var bookmark = this._ds.createBookmarkInContainer(data[1],data[2],data[3],data[4],null,null,resource,0);
if(data[6])
this._ds.Assert(bookmark,this._sideArc,trueVal,true);
}
else
this._ds.createLivemarkInContainer(data[1],data[2],data[5],data[4],resource,0);
break;
case "FOLDER":
title=this._getTitle(element);
desc=this._getDesc(element);
var newresource=this._ds.createFolderInContainer(title,resource,0);
if(desc)
this._ds.Assert(newresource,this._descArc,this._rdfService.GetLiteral(desc),true);
foldersets.push([element,newresource]);
if(this._xbelToolbar && id==this._xbelToolbar)
this._ds.setBookmarksToolbarFolder(newresource);
break;
case "SEPARATOR":
this._createSeparator(resource);
break;
}
}
}
}
},
_createBookmark: function (aID,feedURL)
{
var bookmark=null;
if(aID)
bookmark=this._rdfService.GetResource(aID);
if(!bookmark || this._ds.isBookmarkedResource(bookmark))
bookmark=this._rdfService.GetAnonymousResource();
if(feedURL){
var feed=this._rdfService.GetLiteral(feedURL);
this._assert(bookmark,this._typeArc,this._livemarkVal);
this._assert(bookmark,this._feedArc,feed);
}
else
this._assert(bookmark,this._typeArc,this._bookmarkVal);
this._tempc.AppendElement(bookmark);
return bookmark;
},
get __xbelToolbar()
{
var metadata= this._getMetadata(this._getInfo(this._tempDoc.documentElement));
if(metadata)
return metadata.getAttribute("BookmarksToolbarFolder");
else
return null;
},
_createSeparator: function (aParent)
{
var sep=this._ds.createSeparator();
//Init Container with Parent Folder
if( ! aParent.EqualsString ( this._tempc.Resource.Value ) )
this._tempc.Init(this._ds,aParent);
this._tempc.AppendElement(sep);
},
_getProp: function (aElement,aProp)
{
var value=aElement.getAttribute(aProp);
return (value)? value.replace(/\%3A/g,":") :"";
},
_getBookmarkData:function(aElement)
{
/*0=id,1=name,2=url,3=keyword,4=desc,5=feedURL,6=webPanel*/
var data = [this._getProp(aElement,"id"),"",this._getProp(aElement,"href"),"","","",""];
var childNodes=aElement.childNodes;
for(var i =0; i< childNodes.length; i++)
{
var element=childNodes[i];
if(element.nodeType==1)
{
switch(element.nodeName.toUpperCase())
{
case "TITLE":
data[1]=this._getText(element);
break;
case "INFO":
var metadata=this._getMetadata(element);
if(metadata)
{
data[3]=metadata.getAttribute("ShortcutURL");
data[5]=metadata.getAttribute("FeedURL");
data[6]=metadata.getAttribute("WebPanel");
var icon=metadata.getAttribute("Icon");
if(icon)
this._icons.push([data[2],icon]);
}
break;
case "DESC":
data[4]=this._getText(element);
break;
}
}
}
return data;
},
_getTitle: function (aElement)
{
var title=aElement.firstChild;
while(title && title.nodeName.toUpperCase() != "TITLE")
title=title.nextSibling;
if(title)
return this._getText(title);
return "No Title";
},
_getDesc: function (aElement)
{
var desc=aElement.firstChild;
while(desc && desc.nodeName.toUpperCase() != "DESC")
desc=desc.nextSibling;
if(desc)
return this._getText(desc);
return "";
},
_getInfo: function (aXBEL)
{
var info=aXBEL.firstChild;
while(info && info.nodeName.toUpperCase() != "INFO")
info=info.nextSibling;
return info;
},
_getMetadata: function (aInfo)
{
if(!aInfo)
return null;
var metadata=aInfo.firstChild;
while(metadata && (metadata.nodeName.toUpperCase() != "METADATA"
|| metadata.getAttribute("owner") != this._owner ))
metadata=metadata.nextSibling;
return metadata;
},
_getText: function (element)
{
var str="";
try{
var textnodes=element.childNodes;
for(var i=0; i<textnodes.length ; i++)
{
var textnode=textnodes[0];
if(textnode.nodeType!=1)
str += textnode.nodeValue;
}
}catch(e){alert(e);}
return str;
},
_isXBEL:function()
{
var rv=false;
try{
rv= ( this._tempDoc &&
typeof(this._tempDoc)=="object" &&
this._tempDoc.toString().match(/[object XMLDocument]/) &&
this._tempDoc.documentElement &&
this._tempDoc.documentElement.nodeName.toUpperCase() == "XBEL");
if(this.settings.getBool("publicid",true))
rv = rv && this._tempDoc.doctype &&
(this._tempDoc.doctype.publicId == this._pid);
}catch(e){ rv=false;}
return rv;
},
_unassert: function (aNode)
{
this.__unassert(this._ds,aNode);
},
_assert: function (resource,arc,target)
{
this.__assert(this._ds,resource,arc,target);
},
__assert: function (ds,resource,arc,target)
{
var oldtarget=ds.GetTarget(resource,arc,true);
if(oldtarget) ds.Change(resource,arc,oldtarget,target);
else ds.Assert(resource,arc,target,true);
},
__unassert: function (ds,node)
{
var props=ds.ArcLabelsOut(node);
while(props.hasMoreElements())
{
var prop=props.getNext();
var target=ds.GetTarget(node,prop,true);
ds.Unassert(node,prop,target);
}
},
_killBrowser:function()
{
var nsIWindowMediator = Components.classes['@mozilla.org/appshell/window-mediator;1']
.getService(Components.interfaces.nsIWindowMediator);
var browserWindows=nsIWindowMediator.getZOrderDOMWindowEnumerator('navigator:browser',true);
while(browserWindows.hasMoreElements())
{
try{
var browserWindow=browserWindows.getNext();
browserWindow.QueryInterface(Components.interfaces.nsIDOMWindowInternal);
browserWindow.gBookmarksSynchronizerService.unregObserver();
}catch(e){alert(e)}
}
},
_reliveBrowser:function()
{
var nsIWindowMediator = Components.classes['@mozilla.org/appshell/window-mediator;1']
.getService(Components.interfaces.nsIWindowMediator);
var browserWindows=nsIWindowMediator.getZOrderDOMWindowEnumerator('navigator:browser',true);
while(browserWindows.hasMoreElements())
{
try{
var browserWindow=browserWindows.getNext();
browserWindow.QueryInterface(Components.interfaces.nsIDOMWindowInternal);
browserWindow.gBookmarksSynchronizerService.regObserver();
}catch(e){alert(e)}
}
},
convertToUnicode: function ( aStr )
{
var charset="";
try{
var unicodeConverter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
.createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
if(aStr.match(/encoding=\"(.+)\"/i))
charset=RegExp.$1;
unicodeConverter.charset = (charset)? charset:"UTF-8";
aStr=unicodeConverter.ConvertToUnicode( aStr );
if(charset && charset!="UTF\-16")
aStr=aStr.replace(charset,"UTF-16");
}catch(e){alert(e);}
return aStr;
}
};